﻿#include "ProtocolCustom.h"
#include "utils/Log.h"
#include "uart/UartContext.h"
#include "uart/ProtocolParser.h"
#include "storage/StoragePreferences.h"
#include "string.h"
#include "logic/global_variables.h"
#define RECV_FRAME_LEN    18
#define FRAME_HEAD        0xAA

extern UINT16 getCheckSum(const uint8_t *pData, int len);

static SProtocolParam _s_param;

SProtocolParam& getProtocolParam() {
	return _s_param;
}

namespace protocol{

static Mutex _ack_lock;

Mutex& getAckLock() {
    return _ack_lock;
}

static void _make_protocol_data(const uint8_t *data, SProtocolData &protocol_data) {
	#ifdef TCP_TEST
		#if TCP_MODE == 0
		Tcp::serverSend(data, RECV_FRAME_LEN);
		#endif
	#endif

	int p = 0;
	protocol_data.cmd = data[p+15];
	if(protocol_data.cmd == INQUIRY_CMD_A5){	
        protocol_data.inquiry_a5.mode = data[p];
        protocol_data.inquiry_a5.output_water_control = GETBIT(data[p+1], 0);
        protocol_data.inquiry_a5.output_water_temp = data[p+2];
        protocol_data.inquiry_a5.output_water_output = MAKEWORD(data[p+4], data[p+3]);
        protocol_data.inquiry_a5.output_water_output_total = (uint32_t)data[p+8] | ((uint32_t)data[p+7] << 8) | ((uint32_t)data[p+6] << 16) | ((uint32_t)data[p+5] << 24);

        protocol_data.inquiry_a5.warn_over_temp = GETBIT(data[p+9], 0);
        protocol_data.inquiry_a5.warn_input_water_ntc_error = GETBIT(data[p+9], 3);
        protocol_data.inquiry_a5.warn_descal = GETBIT(data[p+9], 4);
        protocol_data.inquiry_a5.warn_zero_circuit_error = GETBIT(data[p+9], 5);
        protocol_data.inquiry_a5.warn_water_pump_open = GETBIT(data[p+9], 6);
        protocol_data.inquiry_a5.warn_output_water_ntc_error = GETBIT(data[p+9], 7);

        protocol_data.inquiry_a5.warn_output_water_temp_sensor_error = GETBIT(data[p+10], 0);
        protocol_data.inquiry_a5.warn_water_shortage_failure_error = GETBIT(data[p+10],1);
        protocol_data.inquiry_a5.warn_water_pump_short = GETBIT(data[p+10], 2);
        protocol_data.inquiry_a5.warn_heat_film_error = GETBIT(data[p+10], 3);
        protocol_data.inquiry_a5.warn_ice_detection = GETBIT(data[p+10], 4);
        protocol_data.inquiry_a5.warn_input_water_temp_sensor_error = GETBIT(data[p+10], 5);
        protocol_data.inquiry_a5.warn_voltage_sensor_error = GETBIT(data[p+10], 6);
        protocol_data.inquiry_a5.warn_over_high_temp = GETBIT(data[p+10], 7);

        protocol_data.inquiry_a5.warn_low_water_level = GETBIT(data[p+11], 0);
        protocol_data.inquiry_a5.warn_no_heat_tag = GETBIT(data[p+11], 1);
        protocol_data.inquiry_a5.warn_high_water_level = GETBIT(data[p+11], 2);
        protocol_data.inquiry_a5.heat_board_12v_or_uv_switch = GETBIT(data[p+11], 3);
        protocol_data.inquiry_a5.elic1_switch = GETBIT(data[p+11], 4);
        protocol_data.inquiry_a5.input_water_temp = data[p+12];
        protocol_data.inquiry_a5.cmd = data[p+15];

    }else if(protocol_data.cmd == INQUIRY_CMD_E5_B1){
        protocol_data.inquiry_e5_b1.ntc_temp = MAKEWORD(data[p+3], data[p+2]);
        protocol_data.inquiry_e5_b1.soft_version = data[p+8];
        protocol_data.inquiry_e5_b1.temp_correct_value = data[p+9];
        protocol_data.inquiry_e5_b1.customer_code = MAKEWORD(data[p+13], data[p+12]);
        protocol_data.inquiry_e5_b1.cmd = data[p+15];
    }else if(protocol_data.cmd == INQUIRY_CMD_E5_B2){
        protocol_data.inquiry_e5_b2.tds1_value = MAKEWORD(data[p+1], data[p]);
        protocol_data.inquiry_e5_b2.tds2_value = MAKEWORD(data[p+3], data[p+2]);

        protocol_data.inquiry_e5_b2.raw_water_low_level = GETBIT(data[p+4], 0);
        protocol_data.inquiry_e5_b2.raw_water_mid_level = GETBIT(data[p+4], 1);
        protocol_data.inquiry_e5_b2.raw_water_high_level = GETBIT(data[p+4], 2);
        protocol_data.inquiry_e5_b2.clear_water_low_level = GETBIT(data[p+4], 3);
        protocol_data.inquiry_e5_b2.clear_water_mid_level = GETBIT(data[p+4], 4);
        protocol_data.inquiry_e5_b2.clear_water_high_level = GETBIT(data[p+4], 5);
        protocol_data.inquiry_e5_b2.waste_water_low_level = GETBIT(data[p+4], 6);
        protocol_data.inquiry_e5_b2.waste_water_high_level = GETBIT(data[p+4], 7);

        protocol_data.inquiry_e5_b2.uv_light_state = GETBIT(data[p+5], 2);
        protocol_data.inquiry_e5_b2.raw_water_tank_exist_state = GETBIT(data[p+5], 3);
        protocol_data.inquiry_e5_b2.hot_tank_sterilization_state = GETBIT(data[p+5], 4);
        protocol_data.inquiry_e5_b2.clear_water_tank1_output_tag = GETBIT(data[p+5], 5);
        protocol_data.inquiry_e5_b2.clear_water_tank2_output_tag = GETBIT(data[p+5], 6);

        protocol_data.inquiry_e5_b2.leak_state = GETBIT(data[p+6], 0);
        protocol_data.inquiry_e5_b2.clear_water_tank_over = GETBIT(data[p+6], 3);
        protocol_data.inquiry_e5_b2.rfid_reset_level = GETBIT(data[p+6], 6);

        protocol_data.inquiry_e5_b2.hot_tank_ntc_temp = MAKEWORD(data[p+8], data[p+7]);

        protocol_data.inquiry_e5_b2.waste_water_tank_state = GETBIT(data[p+9], 4);
        protocol_data.inquiry_e5_b2.low_power_state = GETBIT(data[p+9], 5);

        protocol_data.inquiry_e5_b2.brine_valve_state = GETBIT(data[p+11], 1);
        protocol_data.inquiry_e5_b2.create_water_pump_state = GETBIT(data[p+11], 2);
        protocol_data.inquiry_e5_b2.tds1_state = GETBIT(data[p+11], 3);
        protocol_data.inquiry_e5_b2.tds2_state = GETBIT(data[p+11], 4);
        protocol_data.inquiry_e5_b2.input_water_valve_state = GETBIT(data[p+11], 5);
        protocol_data.inquiry_e5_b2.hot_water_valve_state = GETBIT(data[p+11], 6);

        protocol_data.inquiry_e5_b2.booster_pump_ad_value = MAKEWORD(data[p+14], data[p+13]);
        protocol_data.inquiry_e5_b2.cmd = data[p+15];

    }else if(protocol_data.cmd == INQUIRY_CMD_E5_E1){
        protocol_data.inquiry_e5_e1.output_water_temp_max = data[p];
        protocol_data.inquiry_e5_e1.output_water_speed = MAKEWORD(data[p+2], data[p+1]);

        protocol_data.inquiry_e5_e1.water_level_enable_tag = GETBIT(data[p+3], 0);
        protocol_data.inquiry_e5_e1.water_low_level_judge = GETBIT(data[p+3], 1);
        protocol_data.inquiry_e5_e1.water_high_level_judge = GETBIT(data[p+3], 2);
        protocol_data.inquiry_e5_e1.raw_water_tank_low_level_judge = GETBIT(data[p+3], 4);
        protocol_data.inquiry_e5_e1.raw_water_tank_exist_judge = GETBIT(data[p+3], 5);
        protocol_data.inquiry_e5_e1.raw_water_tank_caver_judge = GETBIT(data[p+3], 6);
        protocol_data.inquiry_e5_e1.water_tank_over_level_judge = GETBIT(data[p+3], 7);

        protocol_data.inquiry_e5_e1.work_put_power_max = MAKEWORD(data[p+14], data[p+13]);
        protocol_data.inquiry_e5_e1.cmd = data[p+15];
    }else if(protocol_data.cmd == INQUIRY_CMD_E5_FA){
    	protocol_data.inquiry_e5_fa.water_hot_heating_pump = MAKEWORD(data[p+12], data[p+11]);
    }
	
}

bool parse(const uint8_t *data, uint32_t len, const uint8_t *&next, SProtocolData &protocol_data) {
    bool ret = false;
	uint32_t remain_len = len;

#ifdef DEBUG_PRO_RECV
		std::string str;
		char tmp[4] = {4};
		for(uint32_t level1 = 0; level1 < len; ++level1)
		{
			snprintf(tmp, sizeof(tmp), "%.2X ", data[level1]);
			str.append(tmp);
		}
		if(len == 18) {
			if(data[15] == INQUIRY_CMD_A5){
				Global::Log::inquiry_a5_log = str.c_str();
			}else if(data[15] == INQUIRY_CMD_E5_B2){
				Global::Log::inquiry_e5_b2_log = str.c_str();
			}else if(data[15] == INQUIRY_CMD_E5_FA){
				Global::Log::inquiry_e5_fa_log = str.c_str();
			}else if(data[15] == INQUIRY_CMD_E5_E1){
				Global::Log::inquiry_e5_e1_log = str.c_str();
			}
		}

		LOGD("--%d-- --%s-- size:%u 接收数据：%s\n", __LINE__, __FILE__, len, str.c_str());
#endif

	while (remain_len > 0) {
//		if (data[0] != FRAME_HEAD) {
//			data++;
//			remain_len--;
//			continue;
//		}

		if (remain_len < RECV_FRAME_LEN) {
			break;
		}

		if (getCheckSum(data, RECV_FRAME_LEN - 2) != MAKEWORD(data[RECV_FRAME_LEN - 1], data[RECV_FRAME_LEN - 2])) {
//			LOGE("[uart] parse checksum error!\n");
			data++;
			remain_len--;
			continue;
		}

		_make_protocol_data(data, protocol_data);
		data += RECV_FRAME_LEN;
		remain_len -= RECV_FRAME_LEN;
		ret = true;

		break;
	}

	next = (remain_len > 0) ? data : NULL;

	return ret;
}

/**
 * @brief 询问A5
 * @return true 成功，false 失败
 * @note 询问A5命令，用于获取A5命令响应值
 */
static bool inquireA5() {
    uint8_t data[8] = {0};
    data[0] = 0xA5;
    return UartContext::sendTo(UART_TTYS1, data, 1);
}

/**
 * @brief 询问E5_B1
 * @return true 成功，false 失败
 * @note 询问E5_B1命令，用于获取E5_B1命令响应值
 */
static bool inquireE5_B1() {
    uint8_t data[8] = {0};
    data[0] = 0xE5;
    data[1] = 0xB1;
    return UartContext::sendTo(UART_TTYS1, data, 2);
}

/**
 * @brief 询问E5_B2
 * @return true 成功，false 失败
 * @note 询问E5_B2命令，用于获取E5_B2命令响应值
 */
static bool inquireE5_B2() {
    uint8_t data[8] = {0};
    data[0] = 0xE5;
    data[1] = 0xB2;
    return UartContext::sendTo(UART_TTYS1, data, 2);
}

/**
 * @brief 询问E5_E1
 * @return true 成功，false 失败
 * @note 询问E5_E1命令，用于获取E5_E1命令响应值
 */
static bool inquireE5_E1() {
    uint8_t data[8] = {0};
    data[0] = 0xE5;
    data[1] = 0xE1;
    return UartContext::sendTo(UART_TTYS1, data, 2);
}

static bool inquireE5_FA(){
    uint8_t data[8] = {0};
    data[0] = 0xE5;
    data[1] = 0xFA;
    return UartContext::sendTo(UART_TTYS1, data, 2);
}

/**
 * @brief 控制AA_00
 * @return true 成功，false 失败
 * @note 控制AA_00命令，发送控制AA_00命令
*/
static bool controlAA_00() {
    uint8_t data[32] = {0};
    int p = 0;
    data[p++] = FRAME_HEAD;
    data[p++] = _s_param.control_aa_00.mode;
    data[p++] = _s_param.control_aa_00.is_update_water_temp << 7 | _s_param.control_aa_00.water_control;
    data[p++] = _s_param.control_aa_00.water_temp;
    data[p++] = _s_param.control_aa_00.water_output >> 8;
    data[p++] = _s_param.control_aa_00.water_output & 0xFF;
    data[p++] = _s_param.control_aa_00.heat_board_elec3_set << 7 | _s_param.control_aa_00.heat_board_elec3_switch << 6 |
                _s_param.control_aa_00.heat_board_elec2_set << 5 | _s_param.control_aa_00.heat_board_elec2_switch << 4 |
                _s_param.control_aa_00.heat_board_output12v_set << 3 | _s_param.control_aa_00.heat_board_output12v_switch << 2 |
                _s_param.control_aa_00.heat_board_elec1_set << 1 | _s_param.control_aa_00.heat_board_elec1_switch;
    
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
                
    data[p++] = _s_param.control_aa_00.temp_cor_set << 1 | _s_param.control_aa_00.temp_cor_add_sub;
    data[p++] = 0x00;
    data[p++] = _s_param.control_aa_00.cmd = 0x00;

    uint16_t checksum = getCheckSum(data + 1, p - 1);
    data[p++] = checksum >> 8;
    data[p++] = checksum & 0xFF;

    return UartContext::sendTo(UART_TTYS1, data, p);
}

/**
 * @brief 控制AA_E1
 * @return true 成功，false 失败
 * @note 控制AA_E1命令，发送控制AA_E1命令
*/
static bool controlAA_E1() {
    uint8_t data[32] = {0};
    int p = 0;
    data[p++] = FRAME_HEAD;
    data[p++] = _s_param.control_aa_e1.set_put_power_limit << 3 | _s_param.control_aa_e1.set_water_output_min << 1 | _s_param.control_aa_e1.set_water_temp_max;

    data[p++] = _s_param.control_aa_e1.water_temp_max;
    data[p++] = _s_param.control_aa_e1.water_output_speed >> 8;
    data[p++] = _s_param.control_aa_e1.water_output_speed & 0xFF;

    data[p++] = _s_param.control_aa_e1.high_water_level_set << 5 | _s_param.control_aa_e1.high_water_level_way << 4 |
                _s_param.control_aa_e1.low_water_level << 3 | _s_param.control_aa_e1.low_water_level_way << 2 |
                _s_param.control_aa_e1.water_level_switch_set << 1 | _s_param.control_aa_e1.water_level_switch;

    data[p++] = _s_param.control_aa_e1.water_over_set << 7 | _s_param.control_aa_e1.water_over_way << 6 |
                _s_param.control_aa_e1.water_tank_open_set << 5 | _s_param.control_aa_e1.water_tank_open_way << 4 |
                _s_param.control_aa_e1.water_tank_exist_set << 3 | _s_param.control_aa_e1.water_tank_exist_way << 2 |
                _s_param.control_aa_e1.water_tank_low_level_set << 1 | _s_param.control_aa_e1.water_tank_low_level_way;

    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;

    data[p++] = _s_param.control_aa_e1.power >> 8;
    data[p++] = _s_param.control_aa_e1.power & 0xFF;
    data[p++] = 0xE1;

    uint16_t checksum = getCheckSum(data + 1, p - 1);
    data[p++] = checksum >> 8;
    data[p++] = checksum & 0xFF;

    return UartContext::sendTo(UART_TTYS1, data, p);
}

/**
 * @brief 控制AA_A3
 * @return true 成功，false 失败
 * @note 控制AA_A3命令，发送控制AA_A3命令
*/
static bool controlAA_A3() {
    uint8_t data[32] = {0};
    int p = 0;
    data[p++] = FRAME_HEAD;
    data[p++] = _s_param.control_aa_a3.clear_water_tank2_output_set << 7 | _s_param.control_aa_a3.clear_water_tank2_output_switch << 6 |
                _s_param.control_aa_a3.hot_tank_sterilization_set << 5 | _s_param.control_aa_a3.hot_tank_sterilization_switch << 4 |
                _s_param.control_aa_a3.clear_water_tank1_output_set << 3 | _s_param.control_aa_a3.clear_water_tank1_output_switch << 2;

    data[p++] = _s_param.control_aa_a3.led_set << 7 | _s_param.control_aa_a3.led_switch << 6 |
                _s_param.control_aa_a3.rfid_reset_set << 5 | _s_param.control_aa_a3.rfid_reset_level << 4 |
                _s_param.control_aa_a3.dev_lock_tag_set << 3 | _s_param.control_aa_a3.dev_lock_tag_switch << 2 |
                _s_param.control_aa_a3.water_tsd_clear_set << 1 | _s_param.control_aa_a3.water_tsd_clear_switch;

    data[p++] = 0x00;
    data[p++] = 0x00;

    data[p++] = _s_param.control_aa_a3.uv_light_set << 7 | _s_param.control_aa_a3.uv_light_switch << 6 |
                _s_param.control_aa_a3.booster_pump_set << 5 | _s_param.control_aa_a3.booster_pump_switch << 4 |
                _s_param.control_aa_a3.brine_valve_set << 3 | _s_param.control_aa_a3.brine_valve_switch << 2 |
                _s_param.control_aa_a3.reserve_valve_set << 1 | _s_param.control_aa_a3.reserve_valve_switch;

    data[p++] = _s_param.control_aa_a3.hot_water_valve_set << 7 | _s_param.control_aa_a3.hot_water_valve_switch << 6 |
                _s_param.control_aa_a3.input_water_valve_set << 5 | _s_param.control_aa_a3.input_water_valve_switch << 4 |
                _s_param.control_aa_a3.tds2_set << 3 | _s_param.control_aa_a3.tds2_switch << 2 |
                _s_param.control_aa_a3.tds1_set << 1 | _s_param.control_aa_a3.tds1_switch;

    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;

    data[p++] = 0xA3;

    uint16_t checksum = getCheckSum(data + 1, p - 1);
    data[p++] = checksum >> 8;
    data[p++] = checksum & 0xFF;

    return UartContext::sendTo(UART_TTYS1, data, p);
}

static int send_count_aa_00 = 0;
static int send_count_aa_e1 = 0;

/**
 * @brief 制冰控制AA_A1
 * @return true 成功，false 失败
 * @note 制冰控制AA_A1命令，发送控制AA_A1命令
*/
bool ackProduct() {
    uint8_t data[32] = {0};  // 初始化数据缓冲区
    int p = 0;               // 数据指针

    // 添加帧头
    data[p++] = FRAME_HEAD;

    // 字节1
    data[p++] = (_s_param.control_aa_a1.CmdSelfPrimingPump << 7) |
                (_s_param.control_aa_a1.CmdHeatingFilm << 6) |
                (_s_param.control_aa_a1.CmdPushRodMotorForward << 5) |
                (_s_param.control_aa_a1.CmdDrainBoxPump << 4) |
                (_s_param.control_aa_a1.CmdIceMakingPump << 3) |
                (_s_param.control_aa_a1.CmdExhaustFan << 2) |
                (_s_param.control_aa_a1.CmdReservedValve << 1) |
                (_s_param.control_aa_a1.CmdFridgeUVLight << 0);

    // 字节2
    data[p++] = (_s_param.control_aa_a1.CmdIceWaterInletValve << 7) |
                (_s_param.control_aa_a1.CmdIntakeFan << 6) |
                (_s_param.control_aa_a1.CmdColdWaterTankInletValve << 5) |
                (_s_param.control_aa_a1.CmdColdWaterTankCirculationPump << 4) |
                (_s_param.control_aa_a1.CmdColdWaterDiaphragmPump << 3) |
                (_s_param.control_aa_a1.CmdSynchronousMotor << 2) |
                (_s_param.control_aa_a1.CmdDeicingValve << 1) |
                (_s_param.control_aa_a1.CmdColdWaterTankAntiFreeze << 0);

    // 字节3 (bit5-0)
    data[p++] = (_s_param.control_aa_a1.CmdPushRodMotorReverse << 5) |
                (_s_param.control_aa_a1.CmdIceFullIRTransmitter << 4) |
                (_s_param.control_aa_a1.CmdOpenWaterLevelProbe << 3) |
                (_s_param.control_aa_a1.CmdOpenDeicingSensor << 2) |
                (_s_param.control_aa_a1.CmdIceDispenserMotorForward << 1) |
                (_s_param.control_aa_a1.CmdIceDispenserMotorReverse << 0);

    data[p++] = 0x00;
    data[p++] = 0x00;
    data[p++] = 0x00;

    data[p++] = 0xA1;

    uint16_t checksum = getCheckSum(data + 1, p - 1);
    data[p++] = checksum >> 8;
    data[p++] = checksum & 0xFF;

    return UartContext::sendTo(UART_TTYS2, data, p);
}

bool ack() {
    static int cmd_count = 0;
    bool is_send = false;
    Mutex::Autolock _l(getAckLock());
    while(!is_send) {
        switch(cmd_count) {
            case 0:
                inquireA5();
                is_send = true;
                break;
//            case 1:
//                inquireE5_B1();
//                is_send = true;
//                break;
            case 1:
                inquireE5_B2();
                is_send = true;
                break;
            case 2:
                inquireE5_E1();
                is_send = true;
                break;
            case 3:
                controlAA_A3();
                is_send = true;
                break;
            case 4:
                if(_s_param.control_aa_00.water_control != getProtocolData().inquiry_a5.output_water_control || send_count_aa_00 > 0){	//不同步就再发
                    if(send_count_aa_00 > 0){
                        --send_count_aa_00;
                    }
                    controlAA_A3();
                    usleep(100 * 1000);
                    controlAA_00();
                    is_send = true;
                }
                else{
                    is_send = false;
                }
                break;
            case 5:
                if(send_count_aa_e1 > 0){ 
                    --send_count_aa_e1;
                    controlAA_E1();
                    is_send = true;
                }else{
                    is_send = false;
                }
                break;
            case 6:
            	inquireE5_FA();
                is_send = true;
                break;
            default:
                is_send = false;
                break;
        }
        cmd_count = (cmd_count + 1) % 7;
    }
    return true;
}

bool startOutputWater(uint8_t waterTemp, uint16_t waterOutput, bool isUpdateWaterTemp, bool isSend, E_MODE mode) {
    Mutex::Autolock _l(getAckLock());
	if(waterTemp < StoragePreferences::getInt("BoilingPoint", 95)) {
		_s_param.control_aa_00.water_temp = waterTemp;
	}else{
		_s_param.control_aa_00.water_temp = StoragePreferences::getInt("BoilingPoint", 95);
	}

    _s_param.control_aa_00.water_output = 0xffff;
    _s_param.control_aa_00.water_control = 1;
    _s_param.control_aa_00.is_update_water_temp = isUpdateWaterTemp;
    _s_param.control_aa_00.mode = mode;
    send_count_aa_00 = 1;
    if(!isSend){
    	return true;
    }
    // return controlAA_00();
    return true;
}

bool stopOutputWater() {
    Mutex::Autolock _l(getAckLock());
	_s_param.control_aa_00.is_update_water_temp = 0;
    _s_param.control_aa_00.water_control = 0;
    send_count_aa_00 = 1;
    // return controlAA_00();
    return true;
}

bool queryOutputWaterStatus() {
    return inquireA5();
}

bool queryHeatModuleInfo() {
    return inquireE5_B1();
}

bool queryLoadModuleInfo() {
    return inquireE5_B2();
}

bool queryWaterBoxInfo() {
    return inquireE5_E1();
}

bool setCommonTemp(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.reserve_valve_set = 1;
    _s_param.control_aa_a3.reserve_valve_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setColdWater(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.hot_water_valve_set = 1;
    _s_param.control_aa_a3.hot_water_valve_switch = on;

    //冰水流量计计数开关
	_s_param.control_aa_a3.clear_water_tank2_output_set = 1;
	_s_param.control_aa_a3.clear_water_tank2_output_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setWaterIn(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.input_water_valve_set = 1;
    _s_param.control_aa_a3.input_water_valve_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setWasteWater(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.brine_valve_set = 1;
    _s_param.control_aa_a3.brine_valve_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setAirPump(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.booster_pump_set = 1;
    _s_param.control_aa_a3.booster_pump_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setUVLight(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.uv_light_set = 1;
    _s_param.control_aa_a3.uv_light_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setCooling(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.rfid_reset_set = 1;
    _s_param.control_aa_a3.rfid_reset_level = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setCold220V(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.hot_tank_sterilization_set = 1;
    _s_param.control_aa_a3.hot_tank_sterilization_switch = on;


    if(on){
    	 _s_param.control_aa_a1.CmdColdWaterTankCirculationPump = on;
    	_s_param.control_aa_a1.CmdIntakeFan = on;
    	_s_param.control_aa_a1.CmdExhaustFan = on;
    }
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setIceCake(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.hot_tank_sterilization_set = 1;
    _s_param.control_aa_a3.hot_tank_sterilization_switch = on;


    if(on){
    	_s_param.control_aa_a1.CmdIntakeFan = on;
    	_s_param.control_aa_a1.CmdExhaustFan = on;
    }
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool ledControl(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.led_set = 1;
    _s_param.control_aa_a3.led_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setTds(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_a3.tds2_set = 1;
    _s_param.control_aa_a3.tds2_switch = on;
    _s_param.control_aa_a3.tds1_set = 1;
	_s_param.control_aa_a3.tds1_switch = on;
    if(!isSend){
        return true;
    }
    // return controlAA_A3();
    return true;
}

bool setWaterSpeed(int speed, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_e1.set_water_output_min = 1;
    _s_param.control_aa_e1.water_output_speed = speed;
    send_count_aa_e1 = 1;
    // return controlAA_E1();
    return true;
}

bool setWaterSpeedSwitch(bool on, bool isSend) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_e1.set_water_output_min = on;
    send_count_aa_e1 = 1;
    // return controlAA_E1();
    return true;
}

bool setTempCorrection(bool set, bool addOrSub) {    
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_00.temp_cor_set = set;
    _s_param.control_aa_00.temp_cor_add_sub = addOrSub;
    send_count_aa_00 = 1;
    // return controlAA_00();
    return true;
}

bool setWaterTempMax(uint8_t tempMax) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_e1.water_temp_max = tempMax;
    send_count_aa_e1 = 1;
    // return controlAA_E1();
    return true;
}

bool setHeatModule(const ControlAA_E1& project) {
    Mutex::Autolock _l(getAckLock());
    _s_param.control_aa_e1 = project;
    send_count_aa_e1 = 1;
    // return controlAA_E1();
    return true;
}

bool setCommonWaterMode(bool on) {
    Mutex::Autolock _l(getAckLock());
    setLoadSwitch(E_DEV_LOAD_TYPE_COMMON_TEMP, on);
	setLoadSwitch(E_DEV_LOAD_TYPE_WATER_IN, on);
	setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);

//    setCommonTemp(on, false);
//    setAirPump(on, false);
//    setWaterIn(on, false);
    if(on){
		setLoadSwitch(E_DEV_LOAD_TYPE_LED_LIGHT, true);
//        ledControl(true, false);
    }
    // return controlAA_A3();
    return true;
}

bool setHotWaterMode(bool on) {
    Mutex::Autolock _l(getAckLock());

       setLoadSwitch(E_DEV_LOAD_TYPE_WATER_IN, on);
       setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);
       setLoadSwitch(E_DEV_LOAD_TYPE_UV_LIGHT, on);

//    setUVLight(on, false);
//    setWaterIn(on, false);
//    setAirPump(on, false);
    if(on){
    	setLoadSwitch(E_DEV_LOAD_TYPE_LED_LIGHT, true);
//        ledControl(true, false);
    }
    // return controlAA_A3();
    return true;
}

bool setColdWaterMode(bool on) {
    Mutex::Autolock _l(getAckLock());
//    setColdWater(on, false);
//    setWaterIn(on, false);
//    setAirPump(on, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_WATER_IN, on);
      setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);
      setLoadSwitch(E_DEV_LOAD_TYPE_COLD_WATER, on);

    if(on){
//        ledControl(true, false);
    	setLoadSwitch(E_DEV_LOAD_TYPE_LED_LIGHT, true);
    }
    // return controlAA_A3();
    return true;
}

bool setIceDrainWater(bool on) {
    Mutex::Autolock _l(getAckLock());
	 setLoadSwitch(E_DEV_LOAD_TYPE_COLD_WATER, on);
	    setLoadSwitch(E_DEV_LOAD_TYPE_WASTE_WATER, on);
	    setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);
	    setLoadSwitch(E_DEV_LOAD_TYPE_COOLING, on);
//    setCooling(on, false);
//    setAirPump(on, false);
//    setColdWater(on, false);
//    setWasteWater(on, false);
    // return controlAA_A3();
    return true;
}

bool setWaterSupply(bool on) {
    Mutex::Autolock _l(getAckLock());
//    setAirPump(on, false);
//    setWaterIn(on, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);
    setLoadSwitch(E_DEV_LOAD_TYPE_WATER_IN, on);
    // return controlAA_A3();
    return true;
}

bool setFilterClean(bool on) {
    Mutex::Autolock _l(getAckLock());
    setLoadSwitch(E_DEV_LOAD_TYPE_WASTE_WATER, on);
     setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);
     setLoadSwitch(E_DEV_LOAD_TYPE_WATER_IN, on);
//    setAirPump(on, false);
//    setWaterIn(on, false);
//    setWasteWater(on, false);
    // return controlAA_A3();
    return true;
}

bool setDrainWater(bool on) {
    Mutex::Autolock _l(getAckLock());
//    setWasteWater(on, false);
//    setCommonTemp(on, false);
//    setCooling(on, false);
//    setAirPump(on, false);
//    setColdWater(on, false);
//    setUVLight(on, false);

    setLoadSwitch(E_DEV_LOAD_TYPE_COMMON_TEMP, on);
    setLoadSwitch(E_DEV_LOAD_TYPE_COLD_WATER, on);
    setLoadSwitch(E_DEV_LOAD_TYPE_WASTE_WATER, on);
    setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, on);
    setLoadSwitch(E_DEV_LOAD_TYPE_UV_LIGHT, on);
    setLoadSwitch(E_DEV_LOAD_TYPE_COOLING, on);
    // return controlAA_A3();
    return true;
}

bool closeAllValve() {
    Mutex::Autolock _l(getAckLock());
    setLoadSwitch(E_DEV_LOAD_TYPE_COMMON_TEMP, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_COLD_WATER, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_WATER_IN, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_WASTE_WATER, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_AIR_PUMP, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_UV_LIGHT, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_COOLING, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_COMPRESSOR, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_LED_LIGHT, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_TDS1, false);
    setLoadSwitch(E_DEV_LOAD_TYPE_TDS2, false);
//    setCommonTemp(false, false);
//    setColdWater(false, false);
//    setWaterIn(false, false);
//    setWasteWater(false, false);
//    setAirPump(false, false);
//    setUVLight(false, false);
//    setCooling(false, false);
//    setCold220V(false, false);
//    ledControl(false, false);
    // return controlAA_A3();
    return true;
}

bool getLoadSwitch(E_DEV_LOAD_TYPE loadType) {
    switch(loadType) {
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COMMON_TEMP:
            return _s_param.control_aa_a3.reserve_valve_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COLD_WATER:
            return _s_param.control_aa_a3.hot_water_valve_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_WATER_IN:
            return _s_param.control_aa_a3.input_water_valve_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_WASTE_WATER:
            return _s_param.control_aa_a3.brine_valve_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_AIR_PUMP:
            return _s_param.control_aa_a3.booster_pump_switch;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_UV_LIGHT:
            return _s_param.control_aa_a3.hot_water_valve_switch;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COOLING:
            return _s_param.control_aa_a3.rfid_reset_level;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COMPRESSOR:
            return _s_param.control_aa_a3.hot_tank_sterilization_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_LED_LIGHT:
            return _s_param.control_aa_a3.led_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_TDS1:
            return _s_param.control_aa_a3.tds1_switch;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_TDS2:
            return _s_param.control_aa_a3.tds2_switch;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_INTAKE_FAN:
            return _s_param.control_aa_a1.CmdIntakeFan;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_CONDENSER_FAN:
            return _s_param.control_aa_a1.CmdExhaustFan;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_CIRCULATION_PUMP:
            return _s_param.control_aa_a1.CmdColdWaterTankCirculationPump;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_ICETANK_IN:
            return _s_param.control_aa_a1.CmdColdWaterTankInletValve;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_DIAPHRAGM_PUMP:
            return _s_param.control_aa_a1.CmdColdWaterDiaphragmPump;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_ICEMAKE_PUMP:
            return _s_param.control_aa_a1.CmdIceMakingPump;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_MAKEICE_IN:
            return _s_param.control_aa_a1.CmdIceWaterInletValve;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_HEAT_FILM:
            return _s_param.control_aa_a1.CmdHeatingFilm;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_ICE_OUT:
            return _s_param.control_aa_a1.CmdDeicingValve;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_PUSH_FORWARD:
        	return _s_param.control_aa_a1.CmdPushRodMotorReverse;
        	//反过来
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_PUSH_REVERSE:
            return _s_param.control_aa_a1.CmdPushRodMotorForward;

        default:
            return false;
    }
}

void setLoadSwitch(E_DEV_LOAD_TYPE loadType, bool on) {
    switch(loadType) {
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COMMON_TEMP:
            _s_param.control_aa_a3.reserve_valve_set = 1;
            _s_param.control_aa_a3.reserve_valve_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COLD_WATER:
            _s_param.control_aa_a3.hot_water_valve_set = 1;
            _s_param.control_aa_a3.hot_water_valve_switch = on;
            //冰水流量计计数开关
			_s_param.control_aa_a3.clear_water_tank2_output_set = 1;
			_s_param.control_aa_a3.clear_water_tank2_output_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_WATER_IN:
            _s_param.control_aa_a3.input_water_valve_set = 1;
            _s_param.control_aa_a3.input_water_valve_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_WASTE_WATER:
            _s_param.control_aa_a3.brine_valve_set = 1;
            _s_param.control_aa_a3.brine_valve_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_AIR_PUMP:
            _s_param.control_aa_a3.booster_pump_set = 1;
            _s_param.control_aa_a3.booster_pump_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_UV_LIGHT:
//            _s_param.control_aa_a3.uv_light_set = 1;
//            _s_param.control_aa_a3.uv_light_switch = on;
            _s_param.control_aa_a3.hot_water_valve_set = 1;
            _s_param.control_aa_a3.hot_water_valve_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COOLING:
            _s_param.control_aa_a3.rfid_reset_set = 1;
            _s_param.control_aa_a3.rfid_reset_level = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_COMPRESSOR:
            _s_param.control_aa_a3.hot_tank_sterilization_set = 1;
            _s_param.control_aa_a3.hot_tank_sterilization_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_LED_LIGHT:
            _s_param.control_aa_a3.led_set = 1;
            _s_param.control_aa_a3.led_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_TDS1:
            _s_param.control_aa_a3.tds1_set = 1;
            _s_param.control_aa_a3.tds1_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_TDS2:
            _s_param.control_aa_a3.tds2_set = 1;
            _s_param.control_aa_a3.tds2_switch = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_INTAKE_FAN:
            _s_param.control_aa_a1.CmdIntakeFan = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_CONDENSER_FAN:
            _s_param.control_aa_a1.CmdExhaustFan = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_CIRCULATION_PUMP:
            _s_param.control_aa_a1.CmdColdWaterTankCirculationPump = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_ICETANK_IN:
            _s_param.control_aa_a1.CmdColdWaterTankInletValve = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_DIAPHRAGM_PUMP:
            _s_param.control_aa_a1.CmdColdWaterDiaphragmPump = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_ICEMAKE_PUMP:
            _s_param.control_aa_a1.CmdIceMakingPump = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_MAKEICE_IN:
        	_s_param.control_aa_a1.CmdIceWaterInletValve = on;
        	break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_HEAT_FILM:
            _s_param.control_aa_a1.CmdHeatingFilm = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_ICE_OUT:
            _s_param.control_aa_a1.CmdDeicingValve = on;
            break;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_PUSH_FORWARD:
            _s_param.control_aa_a1.CmdPushRodMotorReverse = on;
            //反了
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_PUSH_REVERSE:
            _s_param.control_aa_a1.CmdPushRodMotorForward = on;
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_MOTOR_FORWARD:
            _s_param.control_aa_a1.CmdIceDispenserMotorReverse = on;
            //反了 反过来
            break;
        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_MOTOR_REVERSE:
            _s_param.control_aa_a1.CmdIceDispenserMotorForward = on;
            break;

        case E_DEV_LOAD_TYPE::E_DEV_LOAD_TYPE_CLEANTANK2:
            _s_param.control_aa_a3.clear_water_tank2_output_set = 1;
            _s_param.control_aa_a3.clear_water_tank2_output_switch = on;
            break;

        default:
            break;
    }
}

void setAA_E1()
{
	Mutex::Autolock _l(getAckLock());

	_s_param.control_aa_e1.set_water_temp_max = 1;
	_s_param.control_aa_e1.water_temp_max = 98;

	_s_param.control_aa_e1.set_water_output_min = 1;
	_s_param.control_aa_e1.water_output_speed = 750;

	_s_param.control_aa_e1.set_put_power_limit = 1;
	_s_param.control_aa_e1.power = 0;

	send_count_aa_e1 = 1;
}


}
